<?php
namespace App\Models\MiniHome\Common;

use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Facades\DB;

/**
 * 小程序资源公共管理包
 * Class MiniManageModel
 * @package App\Models\MiniHome\Common
 */
class MiniManageModel
{
    //小程序 APP_ID
    protected $appId = "";

    //小程序 APP_SECRET
    protected $appSecret = "";

    //小程序 SESSION_KEY
    protected $sessionKey = "";

    //小程序用户唯一标识
    protected $openId = "";

    //开放平台用户唯一标识
    protected $unionId = "";

    //缓存过期时间 (S)
    protected $cacheExportTime = 2592000;

    //缓存KEY
    protected $cacheSessionKey = "CACHE_CK_";

    //缓存AccessToken
    protected static $cacheAccessToken = "CACHE_ACCESS_TOKEN";

    public function __construct($openId = "")
    {
        $this->appId = env('MINI_APP_ID', '');
        $this->appSecret = env('MINI_APP_SECRET', '');
        $this->getSessionInfo($openId);
    }

    /**
     * 获取AccessToken
     * @return string
     * @throws \Exception
     */
    public static function getAccessToken() {
        $nowTime = time();
        try {
            $accessTokenInfo = Cache::get(self::$cacheAccessToken, '');
            if ($accessTokenInfo && $accessTokenInfo['expiresIn'] >= $nowTime) {
                return ModelReturn(RETURN_SUCCESS, 'AccessToken 缓存获取', $accessTokenInfo['accessToken']);
            }

            $appId = env('MINI_APP_ID', '');
            $appSecret = env('MINI_APP_SECRET', '');
            $uri = "https://api.weixin.qq.com/cgi-bin/token?";
            $params = [
                'grant_type'    =>  'client_credential',
                'appid'         =>  $appId,
                'secret'        =>  $appSecret
            ];
            $relAccessTokenInfo = CurlGet($uri, $params);
            if ($relAccessTokenInfo['code'] != 200) {
                return ModelReturn($relAccessTokenInfo['code'], $relAccessTokenInfo['msg']);
            }
            $accessTokenInfo = json_decode($relAccessTokenInfo['response']['data'], true);
            if (array_key_exists('errcode', $accessTokenInfo) && $accessTokenInfo['errcode'] != 0) {
                return ModelReturn($accessTokenInfo['errcode'], $accessTokenInfo['errmsg']);
            }

            Cache::put(self::$cacheAccessToken, [
                'accessToken'   =>  $accessTokenInfo['access_token'],
                'expiresIn'     =>  $accessTokenInfo['expires_in'] + time()
            ], $accessTokenInfo['expires_in']);
            return ModelReturn(RETURN_SUCCESS, 'AccessToken 网络获取', $accessTokenInfo['access_token']);
        } catch (\Throwable $e) {
            return ModelReturn($e->getCode(), $e->getMessage());
        }
    }

    /**
     * 获取维信用户的session信息
     * @param $code
     * @return array
     */
    public function code2Session($code) {
        try {
            $appId = env('MINI_APP_ID', '');
            $appSecret = env('MINI_APP_SECRET', '');
            $uri = "https://api.weixin.qq.com/sns/jscode2session?";
            $params = [
                'grant_type'    =>  'authorization_code',
                'appid'         =>  $appId,
                'secret'        =>  $appSecret,
                'js_code'       =>  $code
            ];
            $relSessionInfo = CurlGet($uri, $params);
            if ($relSessionInfo['code'] != 200) {
                return ModelReturn($relSessionInfo['code'], $relSessionInfo['msg']);
            }

            $sessionInfo = json_decode($relSessionInfo['response']['data'], true);
            if (array_key_exists('errcode', $sessionInfo) && $sessionInfo['errcode'] != 0) {
                return ModelReturn($sessionInfo['errcode'], $sessionInfo['errmsg']);
            }

            $this->openId = $sessionInfo['openid'] ?? "";
            $this->unionId = $sessionInfo['unionid'] ?? "";
            $this->sessionKey = $sessionInfo['session_key'] ?? "";

            $cacheKey = $this->cacheSessionKey . $this->openId;
            $cacheData = [
                'openId'    =>  $this->openId,
                'unionId'    =>  $this->unionId,
                'sessionKey'    =>  $this->sessionKey,
            ];
            Cache::put($cacheKey, $cacheData, $this->cacheExportTime);
            return ModelReturn(RETURN_SUCCESS, '获取成功', $cacheData);
        } catch (\Throwable $e) {
            return ModelReturn($e->getCode(), $e->getMessage());
        }
    }

    /**
     * 获取缓存的数据
     * @return bool
     */
    public function getSessionInfo($openId='') {
        $this->openId = $openId ?: $this->openId;
        if (!$this->openId) {
            return ModelReturn(RETURN_CHECK_DATA_DB_FAIL, 'openId不能为空');
        }

        $cacheKey = $this->cacheSessionKey . $this->openId;
        $cacheInfo = Cache::get($cacheKey, '');
        if (!$cacheInfo) {
            $userInfo = DB::table('sc_user_oauth')->where('open_id', $this->openId)->first();
            if (!$userInfo) {
                return ModelReturn(RETURN_CHECK_DATA_DB_FAIL, '用户不不存在');
            }

            $cacheInfo = [
                'openId'    =>  $userInfo->open_id,
                'unionId'   =>  $userInfo->union_id,
                'sessionKey'=>  $userInfo->session_key
            ];
            Cache::add($cacheKey, $cacheInfo, $this->cacheExportTime);
        }

        $this->openId = $cacheInfo['openId'];
        $this->unionId = $cacheInfo['unionId'];
        $this->sessionKey = $cacheInfo['sessionKey'];

        return ModelReturn(RETURN_SUCCESS, '获取成功', $cacheInfo);
    }

    /**
     * 获取UNION_ID
     * @return string
     */
    public function getUnionId(): string
    {
        return $this->unionId;
    }

    /**
     * 获取APP_ID
     * @return string
     */
    public function getAppId(): string
    {
        return $this->appId;
    }

    /**
     * 设置APP_ID
     * @param string $AppId
     */
    public function setAppId(string $appId): void
    {
        $this->appId = $appId;
    }

    /**
     * 获取APP_SECRET
     * @return string
     */
    public function getAppSecret(): string
    {
        return $this->appSecret;
    }

    /**
     * 设置APP_SECRET
     * @param string $AppSecret
     */
    public function setAppSecret(string $appSecret): void
    {
        $this->appSecret = $appSecret;
    }

    /**
     * 获取SESSION KEY
     * @return string
     */
    public function getSessionKey(): string
    {
        return $this->sessionKey;
    }

    /**
     * 设置SESSION KEY
     * @param string $sessionKey
     */
    public function setSessionKey(string $sessionKey): void
    {
        $this->sessionKey = $sessionKey;
    }

    /**
     * 获取OPEN_ID
     * @return string
     */
    public function getOpenId() {
        return $this->openId;
    }

    /**
     * 设置OPEN_ID
     * @param string $openId
     */
    public function setOpenId(string $openId): void
    {
        $this->openId = $openId;
    }

    /**
     * 获取手机号
     * @param $code
     * @return array|string
     */
    public function getPhoneNumber($code) {
        try {
            $accessTokenInfo = self::getAccessToken();
            if ($accessTokenInfo['code'] != RETURN_SUCCESS) {
                return $accessTokenInfo;
            }
            $uri = "https://api.weixin.qq.com/wxa/business/getuserphonenumber?access_token=" . $accessTokenInfo['data'];
            $postData = [
                'code'  =>  $code
            ];
            $relPhoneInfo = CurlPost($uri, $postData,[],false, 'application/json');
            if ($relPhoneInfo['code'] != 200) {
                return ModelReturn($relPhoneInfo['code'], $relPhoneInfo['msg']);
            }

            $phoneInfo = json_decode($relPhoneInfo['response']['data'], true);
            if (array_key_exists('errcode', $phoneInfo) && $phoneInfo['errcode'] != 0) {
                return ModelReturn($phoneInfo['errcode'], $phoneInfo['errmsg']);
            }

            return ModelReturn(RETURN_SUCCESS, '获取手机号成功', $phoneInfo);
        } catch (\Throwable $e) {
            return ModelReturn($e->getCode(), $e->getMessage());
        }
    }

    /**
     * 解密数据
     * @param $encryptedData 解密数据
     * @param $iv 迁移量
     * @return array
     */
    public function decryptData($encryptedData, $iv)
    {
        if (strlen($this->sessionKey) != 24) {
            return ModelReturn(RETURN_CHECK_PARAMS_FAIL, 'SESSION KEY ERROR');
        }
        $aesKey=base64_decode($this->sessionKey);

        if (strlen($iv) != 24) {
            return ModelReturn(RETURN_CHECK_PARAMS_FAIL, 'IV ERROR');
        }
        $aesIV=base64_decode($iv);

        $aesCipher=base64_decode($encryptedData);

        try {
            $result=openssl_decrypt( $aesCipher, "AES-128-CBC", $aesKey, 1, $aesIV);
            if ($result === false) {
                return ModelReturn(RETURN_SESSION_KEY_EXPIRE, '解析数据失败');
            }
            $dataObj=json_decode($result);
            return ModelReturn(RETURN_SUCCESS, '解析成功', $dataObj);
        } catch (\Throwable $e) {
            return ModelReturn($e->getCode(), $e->getMessage());
        }
    }
}